package ferp.android.managers;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ImageSpan;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.TextView;
import ferp.android.GUI;
import ferp.center.Message;
import ferp.core.Version;
import ferp.core.log.Log;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Date;

/**
 * User: igorgok
 * Date: 18/11/2014 10:18
 */
public class NewsManager
{
  //private static final Message hny = new Message(new Message.V1(null, Message.V1.Dates.around(2014, 11, 25, 5), "{#sf03#} С Новым Годом! {#sf03#}"));

  public static void show(final Context context, Collection<Message> messages, final TextView tv)
  {
    // disable for now
    if (true)
      return;

    StringBuilder sb = new StringBuilder(1024);
    Date now = new Date();

    //if (hny.v1.fits(Version.CURRENT, now))
    //  sb.append(hny.v1.text);

    for (Message m : messages)
      if (m.v1.fits(Version.CURRENT, now))
        sb.append(MESSAGE_DELIMITER).append(m.v1.text);

    sb.append(MESSAGE_DELIMITER);

    // debug
/*
    sb.append(MESSAGE_DELIMITER).append("this {#suit_h_e#} is a <b>very</b> long message which probably {#human#} will not fit into the screen");
    sb.append(MESSAGE_DELIMITER).append("if the previous {#android#} message did fit this one will obviously make the ticker move");
    sb.append(MESSAGE_DELIMITER).append("the last {#suit_c_e#} message (number 4)");
    sb.append(MESSAGE_DELIMITER);
*/

    SpannableStringBuilder html = new SpannableStringBuilder(Html.fromHtml(sb.toString()));
    String ticker = html.toString();

    // determine text height to properly size the images
    tv.getPaint().getTextBounds("6", 0, 1, bounds);

    for (int height = bounds.height(), offset = findAndProcessImage(context, ticker, height, 0, html); offset > 0; offset = findAndProcessImage(context, ticker, height, offset, html))
      /* dummy body */;

    Animation transparency = new AlphaAnimation(1f, 0f);

    transparency.setDuration(0);
    transparency.setFillAfter(true);

    tv.setTypeface(GUI.Font.NORMAL);
    tv.setSelected(true);
    tv.setVisibility(View.VISIBLE);
    tv.setText(html);
    tv.startAnimation(transparency);

    Animation appear = new AlphaAnimation(0f, 1f);

    appear.setDuration(1000);
    appear.setFillAfter(true);
    appear.setAnimationListener(new Animation.AnimationListener()
    {
      @Override
      public void onAnimationStart(Animation animation) {}
      @Override
      public void onAnimationEnd(Animation animation)
      {
        try
        {
          Object marquee = getMarqueeObject(tv);

          if (marquee != null)
          {
            Field speed = getMarqueeSpeedField(marquee);

            if (speed != null)
              speed.setFloat(marquee, speed.getFloat(marquee) * 2);
          }
        }
        catch (Exception e)
        {
          Log.error(Log.TAG, e);
        }
      }
      @Override
      public void onAnimationRepeat(Animation animation) {}
    });

    tv.startAnimation(appear);

    tv.setOnTouchListener(new View.OnTouchListener()
    {
      @Override
      public boolean onTouch(View view, MotionEvent me)
      {
        if (me.getAction() != MotionEvent.ACTION_DOWN)
          return false;

        int w = view.getWidth(), back = w / 3, forward = back * 2;
        int x = Math.round(me.getX());

        try
        {
          if (mo == null)
          {
            mo = getMarqueeObject(tv);

            if (mo != null)
            {
              speed.field = getMarqueeSpeedField(mo);
              speed.initial = speed.field.getFloat(mo);
              speed.change = speed.initial / 4;
            }
          }

          if (mo != null)
          {
            float s = speed.field.getFloat(mo);

            if (x > forward)
              speed.field.setFloat(mo, s == 0 ? speed.initial : s + speed.change);
            else
              if (x > back)
              {
                speed.field.setFloat(mo, s == 0 ? speed.before : 0);
                speed.before = s;
              }
              else
                speed.field.setFloat(mo, s == 0 ? -speed.initial : s - speed.change);
          }
        }
        catch (Exception e)
        {
          Log.error(Log.TAG, e);
        }

        return true;
      }

      final class Speed
      {
        private Field field;
        private float initial;
        private float before;
        private float change;
      }

      private Object mo;
      private final Speed speed = new Speed();
    });
  }

  private static final Rect bounds = new Rect();

  private static int findAndProcessImage(Context context, String s, int height, int offset, SpannableStringBuilder sb)
  {
    int index = s.indexOf("{#", offset);

    if (index > -1)
    {
      int start = index + 2, end = s.indexOf("#}", start);

      if (end > 0 && start < end)
      {
        String name = s.substring(start, end);
        Resources r = context.getResources();
        int id = r.getIdentifier(name, "drawable", context.getPackageName());
        Drawable d = r.getDrawable(id);

        if (d != null)
        {
          // limit the dimensions
          d.setBounds(0, 0, height, height);
          // create image span to cover the text with the image name with the real image
          sb.setSpan(new ImageSpan(d, ImageSpan.ALIGN_BASELINE), index, end + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        return end + 2;
      }
    }

    return -1;
  }

  //private static final Spanned MESSAGE_DELIMITER = Html.fromHtml(Message.NBSP + Message.NBSP + "<font color=\"yellow\"><b>•</b></font>" + Message.NBSP + Message.NBSP);
  private static final String MESSAGE_DELIMITER = Message.NBSP + Message.NBSP + "<font color=\"yellow\"><b>•</b></font>" + Message.NBSP + Message.NBSP;

  private static Field getAccessibleField(Object object, String name) throws NoSuchFieldException
  {
    Field f = object.getClass().getDeclaredField(name);

    f.setAccessible(true);

    return f;
  }

  private static Object getMarqueeObject(TextView tv) throws NoSuchFieldException, IllegalAccessException
  {
    return getAccessibleField(tv, "mMarquee").get(tv);
  }

  private static Field getMarqueeSpeedField(Object marquee) throws NoSuchFieldException
  {
    return getAccessibleField(marquee, "mScrollUnit");
  }
}
